package net.esj.basic.dao.querybuilder;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import net.esj.basic.core.engine.annotation.Ignore;
import net.esj.basic.dao.hibernate.HibernateQueryBuilder;
import net.esj.basic.exception.MelonException;

public abstract class AbstractQueryBuilder<T> implements QueryBuilder<T> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private Set<Recorder> recorders  = new LinkedHashSet<Recorder>();
	
	protected Class<T> clazz;
	
	protected AbstractQueryBuilder(Class<T> clazz) {
		this.clazz = clazz;
	}

	@Override
	@Ignore
	public QueryBuilder clone() {
		//QueryBuilder qb = createMe();
		QueryBuilder qb  =QueryBuilderFactory.create(HibernateQueryBuilder.class,clazz);
		try {
			for(Recorder recorder: recorders){
				recorder.getMethod().invoke(qb, recorder.getObjs());
			}
		} catch (Exception e) {
			throw new MelonException("复制QueryBuilde出错", e);
		}finally{
			//((AbstractQueryBuilder)qb).setRecord(new HashSet<Recorder>(recorders));
		}
		return qb;
	}
	
	@Override
	@Ignore
	public QueryBuilder clone4Count() {
		QueryBuilder qb  =QueryBuilderFactory.create(HibernateQueryBuilder.class,clazz);
		try {
			for(Recorder recorder: recorders){
				if(recorder!=null && recorder.getMethod()!=null && recorder.getMethod().getName()!=null && 
						recorder.getMethod().getName().contains("OrderBy")){
					continue;
				}
				recorder.getMethod().invoke(qb, recorder.getObjs());
			}
		} catch (Exception e) {
			throw new MelonException("复制QueryBuilde出错", e);
		}finally{
		}
		return qb;
	}

	@Override
	@Ignore
	public QueryBuilder clone(Class clazz) {
		//QueryBuilder qb  =create(clazz);
		QueryBuilder qb  =QueryBuilderFactory.create(HibernateQueryBuilder.class,clazz);
		try {
			for(Recorder recorder: recorders){
				recorder.getMethod().invoke(qb, recorder.getObjs());
			}
		} catch (Exception e) {
			throw new MelonException("复制QueryBuilde出错", e);
		}finally{
			//((AbstractQueryBuilder)qb).setRecord(new HashSet<Recorder>(recorders));
		}
		return qb;
	}

	protected abstract QueryBuilder createMe();
	
	protected abstract QueryBuilder create(Class clzz);
	
	@Ignore
	protected void record(Method method,Object... objs){
		recorders.add(new Recorder(method, objs));
	}
	
	private void setRecord(Set<Recorder> recorders){
		this.recorders = recorders;
	}
	
	private static class Recorder implements Serializable{
		
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		private Method method;
		
		private Object[] objs;

		private Recorder(Method method, Object[] objs) {
			super();
			this.method = method;
			this.objs = objs;
		}

		public Method getMethod() {
			return method;
		}

		public Object[] getObjs() {
			return objs;
		}
		
	}
}
